package com.hb.core.pojo.sync;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.DbUtil;
import cn.hutool.db.meta.Column;
import cn.hutool.db.meta.MetaUtil;
import cn.hutool.db.meta.Table;
import cn.hutool.log.level.Level;
import com.baomidou.mybatisplus.annotation.TableName;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * 删除与本项目实体类不对应的表
 */
public class CheckColumnOperation {

    public static void main(String[] args) {
        // 数据源对象
        DataSource dataSource = DataSourceBuilder.buildDefault();
        DbUtil.setShowSqlGlobal(false, false, false, Level.INFO);

        // 数据库操作工具
        Db db = Db.use(dataSource);

        // 扫描所有的实体类
        Set<Class<?>> classes = ClassUtil.scanPackage("com.hb.core.pojo", (item) -> {
            Package aPackage = item.getPackage();
            // 只获取entity包下的java类(只获取java实体类)
            return aPackage.getName().endsWith("entity");
        });

        // 临时记录对象, 数据库中表字段名(下划线)
        List<String> columnNames = CollUtil.list(false);

        String tableName;

        for (Class<?> aClass : classes) {
            // 置空容器
            columnNames.clear();

            // 获取类名
            String simpleName = aClass.getSimpleName();

            // mybatis-plus注解
            TableName annotation = aClass.getAnnotation(TableName.class);
            if (annotation == null) {
                // 没有注解的默认为将类名改为下划线分割的作为表名
                tableName = StrUtil.toUnderlineCase(simpleName);
            } else {
                tableName = annotation.value();
            }

            // 项目表结构与实体类结构特殊, 在此不作处理(需要手动对照)
            if ("trade_project".equals(tableName)) {
                continue;
            }

            // 获取数据库中所有的表
            Table table = MetaUtil.getTableMeta(dataSource, tableName);
            Collection<Column> tableColumns = table.getColumns();
            if (tableColumns.size() == 0) {
                // 表没有字段表示该表不存在
                continue;
            }

            // 获取表中的所有列
            for (Column column : tableColumns) {
                columnNames.add(column.getName());
            }

            Field[] fields = ReflectUtil.getFields(aClass);
            for (Field field : fields) {
                String fieldName = field.getName();
                // 过滤无用字段 start
                if ("serialVersionUID".equals(fieldName)) {
                    continue;
                }
                if ("DEFAULT_CURRENT".equals(fieldName)) {
                    continue;
                }
                if ("DEFAULT_LIMIT".equals(fieldName)) {
                    continue;
                }
                if ("currentPage".equals(fieldName)) {
                    continue;
                }
                if ("pageSize".equals(fieldName)) {
                    continue;
                }
                if ("total".equals(fieldName)) {
                    continue;
                }
                // 过滤无用字段 end

                // 与实体类对应的字段忽略
                String columnName = StrUtil.toUnderlineCase(fieldName);
                columnNames.remove(columnName);
            }

            // 完全对应, 忽略
            if (columnNames.size() == 0) {
                System.out.println("[" + tableName + "]表结构与实体类对应, 忽略");
                continue;
            }

            System.err.println("处理表名: " + tableName);
            for (String columnDiff : columnNames) {
                System.err.println("移除 " + tableName + "." + columnDiff);
                String dropColumnSql = "ALTER TABLE `" + tableName + "` DROP COLUMN `" + columnDiff + "`";
                try {
                    db.execute(dropColumnSql);
                } catch (SQLException e) {
                    System.err.println(e.getMessage());
                }
            }
        }
        System.out.println(">>>>>>>>>>>>>>>>处理完成 !");
    }

}
